package com.betterjr.modules.application.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Service;

import com.betterjr.common.service.BaseService;
import com.betterjr.common.utils.BTAssert;
import com.betterjr.common.utils.Collections3;
import com.betterjr.common.utils.QueryTermBuilder;
import com.betterjr.common.utils.UserUtils;
import com.betterjr.modules.application.IApplicationUndercarriage;
import com.betterjr.modules.application.dao.ApplicationOperorgMapper;
import com.betterjr.modules.application.data.ApplicationConstantCollections;
import com.betterjr.modules.application.data.ApplicationGroupConstantCollections;
import com.betterjr.modules.application.data.ApplicationOperorgConstantCollections;
import com.betterjr.modules.application.entity.Application;
import com.betterjr.modules.application.entity.ApplicationOperorg;
import com.betterjr.modules.customer.service.CustMechBaseService;
import com.google.common.collect.Lists;

/**
 * 
 * @ClassName: ApplicationOperorgService 
 * @Description: 应用机构服务 
 * @author xuyp
 * @date 2017年11月17日 下午6:06:12 
 *
 */
@Service
public class ApplicationOperorgService extends BaseService<ApplicationOperorgMapper, ApplicationOperorg>
        implements IApplicationUndercarriage, ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Autowired
    private ApplicationService applicationService;

    @Autowired
    private ApplicationGroupService groupService;

    @Autowired
    private CustMechBaseService custService;

    /**
     * 
     * @Title: queryApplications 
     * @Description: 查询当前机构下所有应用的集合
     * @param anApplcationTypeId
     * @param anApplcationGroupId
     * @param anBusinStatus
     * @return TODO(说明)
     * @throws 
     * @author xuyp
     * @date 2017年11月16日 下午4:22:25
     */
    @SuppressWarnings("unchecked")
    public List<ApplicationOperorg> queryApplicationOperorgs(Long anApplcationTypeId, Long anApplcationGroupId,
            String anBusinStatus) {

        if (StringUtils.isBlank(anBusinStatus)) {
            BTAssert.notNull(null, "查询条件异常,操作失败");
        }
        Map<String, Object> map = QueryTermBuilder.newInstance().put("businStatus", anBusinStatus)
                .put("operOrg", UserUtils.getOperatorInfo().getOperOrg()).build();
        if (anBusinStatus.contains(ApplicationGroupConstantCollections.SYSTEM_VALUE_FILE_SEPARATOR)) {
            map.put("businStatus",
                    anBusinStatus.split(ApplicationGroupConstantCollections.SYSTEM_VALUE_FILE_SEPARATOR));
        }

        if (null != anApplcationTypeId) {
            map.put("applicationTypeId", anApplcationTypeId);
        }

        if (null != anApplcationGroupId) {
            map.put("applicationGroupId", anApplcationGroupId);
        }

        List<ApplicationOperorg> list = this.selectByProperty(map, "id Desc");

        for (ApplicationOperorg applicationOperorg : list) {
            applicationOperorg.setApplicationName(
                    applicationService.findApplicationNameById(applicationOperorg.getApplicationId()));
            applicationOperorg.setApplicationGroupName(
                    groupService.findApplicationGroupNameById(applicationOperorg.getApplicationGroupId()));
        }
        return list;
    }

    /**
     * 
     * @Title: queryApplication 
     * @Description: 返回应用对象 
     * @param anApplcationTypeId
     * @param anApplcationGroupId
     * @param anBusinStatus   状态 1未生效 2已生效 9已失效
     * @return  返回应用对象
     * @throws 
     * @author xuyp
     * @date 2017年11月16日 下午5:32:06
     */
    public List<Application> queryApplication(Long anApplcationTypeId, Long anApplcationGroupId, String anBusinStatus) {

        List<ApplicationOperorg> list = queryApplicationOperorgs(anApplcationTypeId, anApplcationGroupId,
                anBusinStatus);
        List<Application> applications = new ArrayList<>(list.size());
        for (ApplicationOperorg operorg : list) {
            applications.add(applicationService.selectByPrimaryKey(operorg.getApplicationId()));
        }
        return applications;

    }

    /**
     * 
     * @Title: saveAssignedApplicationToCust 
     * @Description: 分配应用给企业
     * @param anApplicationids
     * @param anCustNo
     * @param anBusinStatus
     * @return List<ApplicationOperorg>
     * @throws 
     * @author xuyp
     * @date 2017年11月25日 下午1:35:48
     */
    public List<ApplicationOperorg> saveAssignedApplicationToCust(String anApplicationids, Long anCustNo,
            String anBusinStatus) {

        if (StringUtils.isNoneBlank(anApplicationids) && null != anCustNo) {
            List<Long> applicationIdsList = convertToLongApplicationidsList(anApplicationids);
            if (!Collections3.isEmpty(applicationIdsList)) {
                // 查询当前分配员所拥有的应用列表
                List<ApplicationOperorg> applicationOperorgList = queryListByApplicationids(applicationIdsList);
                // 保存或者更新应用机构表信息
                return saveAddOrModifyByApplicationOperorg(applicationOperorgList, anCustNo, anBusinStatus);
            }
        }

        return new ArrayList<>();

    }

    /**
     * 
     * @Title: saveAddByApplication 
     * @Description:通过应用插入或者更新机构应用表 
     * @param anApplication   应用对象
     * @param anBusinStatus  状态  状态 1未生效 2已生效 3已失效
     * @return TODO(说明)
     * @throws 
     * @author xuyp
     * @date 2017年11月16日 下午1:54:27
     */

    public ApplicationOperorg saveAddByApplication(Application anApplication, String anBusinStatus) {

        // 判断是否需要同步更新状态
        if (saveUpdateByApplication(anApplication, anBusinStatus)) {
            return null;
        }

        ApplicationOperorg applicationOperorg = new ApplicationOperorg();

        applicationOperorg = convertOperorgWithApplicaiton(anApplication);
        applicationOperorg.setBusinStatus(anBusinStatus);
        applicationOperorg.saveAddValue();

        this.insertSelective(applicationOperorg);
        return applicationOperorg;

    }

    /**
     * 
     * @Title: saveUpdateByApplication 
     * @Description:更新某条应用的状态
     * @param anApplication
     * @param anBusinStatus
     * @return true  表示有更新    false  表示没有更新
     * @throws 
     * @author xuyp
     * @date 2017年11月22日 上午9:45:25
     */
    @SuppressWarnings("unchecked")
    private boolean saveUpdateByApplication(Application anApplication, String anBusinStatus) {

        boolean flag = false;
        Map<String, Object> map = QueryTermBuilder.newInstance().put("applicationId", anApplication.getId())
                .put("operOrg", anApplication.getOperOrg())
                .put("businStatus",
                        new String[] { ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_NOEFFECTIVE,
                                ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_EFFECTIVE })
                .build();

        List<ApplicationOperorg> list = this.selectByProperty(map, "id Desc");
        for (ApplicationOperorg applicationOperorg : list) {
            applicationOperorg.setBusinStatus(anBusinStatus);;

            this.updateByPrimaryKeySelective(applicationOperorg);
            flag = true;
        }
        return flag;
    }

    /**
     * 
     * @Title: saveModifyByApplication 
     * @Description: 通过应用修改应用机构表信息
     * @param anApplication
     * @return TODO(说明)
     * @throws 
     * @author xuyp
     * @date 2017年11月16日 下午2:15:08
     */
    @SuppressWarnings("unchecked")
    public List<ApplicationOperorg> saveModifyByApplication(Application anApplication) {

        Map<String, Object> map = QueryTermBuilder.newInstance().put("applicationId", anApplication.getId())
                .put("operOrg", anApplication.getOperOrg())
                .put("businStatus",
                        new String[] { ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_NOEFFECTIVE,
                                ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_EFFECTIVE })
                .build();
        List<ApplicationOperorg> list = this.selectByProperty(map, "id Desc");
        for (ApplicationOperorg applicationOperorg : list) {
            applicationOperorg.setApplicationGroupId(anApplication.getApplicationGroupId());
            applicationOperorg.setApplicationTypeId(anApplication.getApplicationTypeId());
            this.updateByPrimaryKeySelective(applicationOperorg);
        }

        return list;

    }

    /**
     * 
     * @Title: saveApplicationBusinStatusSynchronized 
     * @Description: 修改应用状态同步上下架信息 
     * @param application TODO(说明)
     * @throws 
     * @author xuyp
     * @date 2017年11月16日 下午2:35:53
     */
    public void saveApplicationBusinStatusSynchronized(Application application) {

        if (ApplicationConstantCollections.APPLICATION_BUSINSTATUS_PUBLISHING.equals(application.getBusinStatus())) {
            // 应用上架同步
            saveAddByApplication(application,
                    ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_EFFECTIVE);
        } else {
            // 应用下架或者卸载同步同步
            List<IApplicationUndercarriage> list = queryUndercarriageInterfaces();
            for (IApplicationUndercarriage iApplicationUndercarriage : list) {
                iApplicationUndercarriage.saveUndercarriageApplication(application.getId());
            }
        }

    }

    /**
     * 实现接口，应用下架
     * <p>Overriding Method of saveUndercarriageApplication</p>  
     * <p>Description: </p> 
     * @param anApplicationId 
     * @see com.betterjr.modules.application.IApplicationUndercarriage#saveUndercarriageApplication(java.lang.Long) 
     * @author xuyp
     * @date 2017年11月16日 下午2:40:46
     */
    @Override
    public void saveUndercarriageApplication(Long anApplicationId) {

        if (null != anApplicationId) {
            Application application = applicationService.selectByPrimaryKey(anApplicationId);
            if (null != application) {
                saveUndercarriageApplicationOperorg(anApplicationId);
            }
        }

    }

    /**
     * 
     * @Title: saveUndercarriageApplicationOperorg 
     * @Description: 应用机构表下架应用 
     * @param anApplicationId
     * @return TODO(说明)
     * @throws 
     * @author xuyp
     * @date 2017年11月16日 下午3:15:33
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private List<ApplicationOperorg> saveUndercarriageApplicationOperorg(Long anApplicationId) {

        Map map = QueryTermBuilder.newInstance().put("applicationId", anApplicationId)
                .put("businStatus",
                        new String[] { ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_NOEFFECTIVE,
                                ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_EFFECTIVE })
                .build();
        List<ApplicationOperorg> list = this.selectByProperty(map);
        for (ApplicationOperorg applicationOperorg : list) {
            applicationOperorg
                    .setBusinStatus(ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_DELETED);
            this.updateByPrimaryKeySelective(applicationOperorg);
        }

        return list;

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;

    }

    /**
     * 
     * @Title: convertOperorgWithApplicaiton 
     * @Description: 将应用对象转换成应用机构对象
     * @param anApplication
     * @return TODO(说明)
     * @throws 
     * @author xuyp
     * @date 2017年11月16日 下午2:05:57
     */
    private ApplicationOperorg convertOperorgWithApplicaiton(Application anApplication) {

        ApplicationOperorg applicationOperorg = new ApplicationOperorg();

        applicationOperorg.setApplicationGroupId(anApplication.getApplicationGroupId());
        applicationOperorg.setApplicationId(anApplication.getId());
        applicationOperorg.setApplicationTypeId(anApplication.getId());
        applicationOperorg.setOperOrg(anApplication.getOperOrg());

        return applicationOperorg;
    }

    /**
     * 
     * @Title: queryUndercarriageInterfaces 
     * @Description: 查询spring容器中所有注册的下架应用的服务类
     * @return TODO(说明)
     * @throws 
     * @author xuyp
     * @date 2017年11月16日 下午3:00:20
     */
    private List<IApplicationUndercarriage> queryUndercarriageInterfaces() {
        String[] namesForType = applicationContext.getBeanNamesForType(IApplicationUndercarriage.class);
        List<IApplicationUndercarriage> lists = new ArrayList<>(namesForType.length);
        for (String string : namesForType) {
            lists.add((IApplicationUndercarriage) applicationContext.getBean(string));
        }

        return lists;
    }

    /**
     * 
     * @Title: convertToLongApplicationidsList 
     * @Description: 将应用id字符串集合转成long集合 
     * @param anApplicationids
     * @return list<Long>
     * @throws 
     * @author xuyp
     * @date 2017年11月25日 上午11:04:39
     */
    private List<Long> convertToLongApplicationidsList(String anApplicationids) {

        if (StringUtils.isNoneBlank(anApplicationids)) {

            String[] array = org.springframework.util.StringUtils.tokenizeToStringArray(anApplicationids,
                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
            List<Long> list = new ArrayList<>(array.length);
            for (String str : array) {
                try {
                    list.add(Long.parseLong(str));
                }
                catch (Exception e) {

                }
            }

            return list;

        }

        return null;
    }

    /**
     * 
     * @Title: queryListByApplicationids 
     * @Description: 查询属于自己企业的应用集合列表 
     * @param applicationIdsList
     * @return  List<ApplicationOperorg>
     * @throws 
     * @author xuyp
     * @date 2017年11月25日 上午11:07:11
     */
    @SuppressWarnings("unchecked")
    private List<ApplicationOperorg> queryListByApplicationids(List<Long> applicationIdsList) {

        if (!Collections3.isEmpty(applicationIdsList)) {
            Map<String, Object> map = QueryTermBuilder.newInstance().put("applicationId", applicationIdsList)
                    .put("operOrg", UserUtils.getOperatorInfo().getOperOrg())
                    .put("businStatus", ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_EFFECTIVE)
                    .build();

            return this.selectByProperty(map, "id Desc");

        }
        return null;
    }

    /**
     * 保存或者更新应用机构表信息
     * @Title: saveAddOrModifyByApplicationOperorg 
     * @Description: 保存或者更新应用机构表信息
     * @param applicationOperorgList
     * @param anCustNo
     * @param anBusinStatus
     * @return List<ApplicationOperorg>
     * @throws 
     * @author xuyp
     * @date 2017年11月25日 上午11:19:36
     */
    private List<ApplicationOperorg> saveAddOrModifyByApplicationOperorg(
            List<ApplicationOperorg> applicationOperorgList, Long anCustNo, String anBusinStatus) {

        if (!Collections3.isEmpty(applicationOperorgList) && null != anCustNo) {

            String operOrg = custService.findCustMechBaseByCustNo(anCustNo).getOperOrg();
            for (ApplicationOperorg applicationOperorg : applicationOperorgList) {
                saveAddOrModifyByApplicationOperorg(applicationOperorg, operOrg, anBusinStatus);
            }

            return applicationOperorgList;

        }

        return Lists.newArrayList();

    }

    @SuppressWarnings("unchecked")
    private ApplicationOperorg saveAddOrModifyByApplicationOperorg(ApplicationOperorg applicationOperorg,
            String anOperorg, String anBusinStatus) {
        Map<String, Object> map = QueryTermBuilder.newInstance()
                .put("applicationId", applicationOperorg.getApplicationId()).put("operOrg", anOperorg)
                .put("businStatus",
                        new String[] { ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_NOEFFECTIVE,
                                ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_EFFECTIVE })
                .build();

        List<ApplicationOperorg> list = this.selectByProperty(map);
        if (!Collections3.isEmpty(list)) {
            // 修改
            if (list.size() > 1) {
                for (int i = 1; i < list.size(); i++) {

                    saveModifyBusinStatus(list.get(0),
                            ApplicationOperorgConstantCollections.APPLICATIONOPERORG_BUSINSTATUS_DELETED);
                }
            }
            return saveModifyBusinStatus(list.get(0), anBusinStatus);
        } else {
            // 新增

            return saveAddByBusinStatus(applicationOperorg, anOperorg, anBusinStatus);
        }
    }

    /**
     * 
     * @Title: saveAddByBusinStatus 
     * @Description: 新增一条记录 
     * @param applicationOperorg
     * @param anOperorg
     * @param anBusinStatus
     * @return 
     * @throws 
     * @author xuyp
     * @date 2017年11月25日 上午11:58:42
     */
    private ApplicationOperorg saveAddByBusinStatus(ApplicationOperorg applicationOperorg, String anOperorg,
            String anBusinStatus) {

        applicationOperorg.saveAddValue();
        applicationOperorg.setOperOrg(anOperorg);
        applicationOperorg.setBusinStatus(anBusinStatus);
        this.insertSelective(applicationOperorg);
        return applicationOperorg;
    }

    /**
     * 
     * @Title: saveModifyBusinStatus 
     * @Description: 修改单条记录的状态 
     * @param applicationOperorg
     * @param anBusinStatus
     * @return 修改单条记录的状态
     * @throws 
     * @author xuyp
     * @date 2017年11月25日 上午11:57:06
     */
    private ApplicationOperorg saveModifyBusinStatus(ApplicationOperorg applicationOperorg, String anBusinStatus) {

        if (applicationOperorg != null && StringUtils.isNoneBlank(anBusinStatus)) {

            applicationOperorg.setBusinStatus(anBusinStatus);

            this.updateByPrimaryKeySelective(applicationOperorg);

        }

        return applicationOperorg;
    }

}
